package com.mirama.framework.rabbitmq;

import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.Random;

/**
 * 消息接收器/消费者
 * Exchange和RoutingKey、queue不同时，每条消息都会发送到多个队列，每个队列里面只有一个消费者可以消费
 * Exchange和RoutingKey、queue都相同，每条消息只有一个消费者可以消费
 */
@Slf4j
@Component
public class MqReceiver {

    @RabbitHandler
    @RabbitListener(queues = MqConstants.MQ_DIRECT_QUEUE)
    public void process(Map<String, Object> msgMap, Message msg, Channel channel) throws IOException {

        log.info("{} Receiver : {}", msg.getMessageProperties().getConsumerQueue(), JSONUtil.toJsonStr(msgMap));

        String msgStr = MapUtil.getStr(msgMap, "msg");

        // long deliveryTag, boolean multiple，手工ACK后，说明正常消费，队列会删除消息
        int flag = new Random().nextInt(100) % 3;

        if (flag == 0) {
            // 接收消息，正常消费
            log.info("正常消费消息：{}", msgStr);
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
        } else if (flag == 1) {
            // 拒绝消息，重新入队列
            log.info("拒绝消息，重新入队列：{}", msgStr);
            channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, true);
        } else if (flag == 2) {
            // 拒绝消息，抛弃
            log.info("抛弃消息：{}", msgStr);
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
        }
    }

}
